package com.nlscan.ncomgateway.core.sdk.tcp

import android.content.Context
import android.os.Handler
import android.os.Looper
import com.nlscan.ble.util.NLogUtil
import com.nlscan.qdkit.common.core.app.App
import com.nlscan.ncomgateway.core.data.preference.SettingsPreferenceManager
import com.xuhao.didi.socket.client.impl.client.action.ActionDispatcher
import com.xuhao.didi.socket.client.sdk.OkSocket
import com.xuhao.didi.socket.client.sdk.client.ConnectionInfo
import com.xuhao.didi.socket.client.sdk.client.OkSocketOptions
import com.xuhao.didi.socket.client.sdk.client.action.ISocketActionListener
import com.xuhao.didi.socket.client.sdk.client.action.SocketActionAdapter
import com.xuhao.didi.socket.client.sdk.client.connection.IConnectionManager

object TcpManager {

    const val CONNECTION_STATE_IDLE = -1
    const val CONNECTION_STATE_DISCONNECTED = 0
    const val CONNECTION_STATE_CONNECTING = 1
    const val CONNECTION_STATE_CONNECTED = 2
    const val CONNECTION_STATE_DISCONNECTING = 3

    var mManager: IConnectionManager? = null


    var observers = mutableListOf<ISocketActionListener>()

    var mHandler = Handler(Looper.myLooper()!!)
    var mConnectionInfo: ConnectionInfo? = null

    @Synchronized
    fun registerObserver(observer: ISocketActionListener) {

//        var registered = false
//        {
//            val it: MutableIterator<ObserverInfo> = observerInfos.iterator()
//            while (it.hasNext()) {
//                val info = it.next()
//                val o = info.weakObserver.get()
//                if (o == null) {
//                    it.remove()
//                } else if (o === observer) {
//                    registered = true
//                }
//            }
//        }

        observers.add(observer)
        mManager?.registerReceiver(observer)


    }

    @Synchronized
    fun unregisterObserver(observer: ISocketActionListener) {
        observers.remove(observer)
        mManager?.unRegisterReceiver(observer)
    }

    @Synchronized
    fun unregisterAll() {
        observers.forEach {
            mManager?.unRegisterReceiver(it)
        }
        observers.clear()
    }

    @Synchronized
    fun createTcpConnection(
        hostname: String,
        iPort: Int
    ) {
        mConnectionInfo = ConnectionInfo(hostname, iPort)
        val options = OkSocketOptions.Builder()
            //[update] 增加重连机制
            //.setReconnectionManager(NoneReconnect())
            .setReconnectionManager(OkSocketOptions.getDefault().reconnectionManager)
            .setConnectTimeoutSecond(10)
            .setCallbackThreadModeToken(object : OkSocketOptions.ThreadModeToken() {
                override fun handleCallbackEvent(runnable: ActionDispatcher.ActionRunnable?) {
                    runnable?.let {
//                        getAppContext().Handler().post(it)
                        mHandler.post(it)
                    }
                }

            })
            .build()

        if (mManager != null) {
            mManager?.disconnect()

            observers.forEach {
                mManager?.unRegisterReceiver(it)
            }
        }

        mManager = OkSocket.open(mConnectionInfo)
            .option(options)
        observers.forEach {
            mManager?.registerReceiver(it)

        }

    }

    @Synchronized
    fun connect() {
        if (mManager == null) {
            // TODO: 增加错误码
            notifySocketConnectionFailed(Exception("tcp connection no create!"))
            return
        }
        mManager?.let {
            if (it.isConnect) {
                //debug0411
                NLogUtil.dTag("TAG41", "tcp 已连接")
                notifySocketConnectionSuccess()
                return
            }
            it.connect()
        }
    }

    fun isConnect() = mManager?.isConnect?:false

    fun getConnectState(): Int {
        return if (mManager == null) {
            CONNECTION_STATE_DISCONNECTED
        } else {
            if (mManager!!.isConnect) {
                CONNECTION_STATE_CONNECTED
            } else {
                CONNECTION_STATE_DISCONNECTED
            }
        }
    }

    fun autoConnect() {
        val ipAddress = SettingsPreferenceManager.getIpOutputHostname()
        val port = SettingsPreferenceManager.getIpOutputPort()
        if (ipAddress.isNotEmpty() && port.isNotEmpty()) {
            NLogUtil.i("auto connect")
            createTcpConnection(ipAddress, port.toInt())
            connect()
        }
    }


    fun release() {
        mManager?.disconnect()
        unregisterAll()
    }

    private fun getAppContext(): Context {
        return App.getInstance()
    }

    private fun notifySocketConnectionFailed(e: Exception) {
        observers.forEach {
            it.onSocketConnectionFailed(mConnectionInfo, "", e)
        }
    }

    private fun notifySocketConnectionSuccess() {
        observers.forEach {
            it.onSocketConnectionSuccess(mConnectionInfo, "")
        }
    }


    class CustomSocketActionAdapter : SocketActionAdapter() {

        override fun onSocketConnectionSuccess(info: ConnectionInfo?, action: String?) {
            super.onSocketConnectionSuccess(info, action)
            // TODO: 当前临时写连接成功
//            mManager.send()

        }

        override fun onSocketConnectionFailed(
            info: ConnectionInfo?,
            action: String?,
            e: java.lang.Exception?
        ) {
            super.onSocketConnectionFailed(info, action, e)

        }
    }

}